(function () {
  // promise构造函数
  function myPromise(executor) {
    var that = this;
    // 类型检查
    if (typeof executor !== 'function') throw new Error('the executor must be a function');
    if (!(that instanceof myPromise)) throw new Error('should be myPromise')
    // 初始化实例属性
    this.status = 'pending';
    this.data = undefined;
    this.onfulfilledCallbacks = [];
    this.onrejectedCallbacks = [];
    // 初始化内置函数
    function resolve(value) {
      if (that.status !== 'pending') return;
      that.status = 'resolved';
      that.data = value;
      if (that.onfulfilledCallbacks.length > 0) {
        setTimeout(function () {
          that.onfulfilledCallbacks.forEach(callback => {
            callback(value)
          })
        })
      }
    }

    function reject(reason) {
      if (that.status !== 'pending') return;
      that.status = 'rejected';
      that.data = reason;
      if (that.onrejectedCallbacks.length > 0) {
        setTimeout(function () {
          that.onrejectedCallbacks.forEach(callback => {
            callback(reason)
          })
        })
      }
    }
    // 执行器函数同步执行
    try {
      executor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }
  // 类型检查处理
  if (typeof Symbol !== undefined) myPromise[Symbol.toString] = 'myPromise';
  // IIFE挂载
  window.myPromise = myPromise;
})()

myPromise.prototype.then = function (onResolved, onRejected) {
  // then回调函数容错预置
  onResolved = typeof onResolved === 'function' ? onResolved : function (value) {
    return value
  };
  onRejected = typeof onRejected === 'function' ? onRejected : function (reason) {
    throw reason
  };
  var that = this;
  var x;
  // 根据回调的结果确定新promise的状态如何
  function handle(newPromise, x, resolve, reject) {
    if (newPromise === x) throw new TypeError('Chain is found');
    // 返回值是promise
    if (x instanceof myPromise) {
      try {
        x.then(resolve, reject);
      } catch (error) {
        reject(error)
      }
      return;
    }
    // 返回值不是promise
    resolve(x)
  }
  var newPromise = new myPromise(function (resolve, reject) {
    switch (that.status) {
      // 指定回调前已经存在状态了
      case 'resolved':
        setTimeout(function () {
          try {
            x = onResolved(that.data);
            handle(newPromise, x, resolve, reject)
          } catch (error) {
            reject(error)
          }
        })
        break;
      case 'rejected':
        try {
          x = onRejected(that.data);
          handle(newPromise, x, resolve, reject)
        } catch (error) {
          reject(error)
        }
        break;
      // 指定回调前并没有改好状态
      default:
        that.onfulfilledCallbacks.push(function (value) {
          try {
            x = onResolved(value)
            handle(newPromise, x, resolve, reject)
          } catch (error) {
            reject(error)
          }
        })
        that.onrejectedCallbacks.push(function (reason) {
          try {
            x = onRejected(reason)
            handle(newPromise, x, resolve, reject)
          } catch (error) {
            reject(error)
          }
        })
        break;
    }
  })
  return newPromise;
}
myPromise.prototype.catch = function (onRejected) {
  if (typeof onRejected !== 'function') throw new Error('onRejected must be a function')
  return this.then(undefined, onRejected);
}
// finally，不接受任何参数，之前的回调完成后不管状态，均执行
myPromise.prototype.finally = function (onFinally) {
  return this.then(onFinally, onFinally);
}






myPromise.resolve = function (value) {
  return new myPromise((resolve, reject) => {
    if (value instanceof myPromise) {
      value.then(resolve, reject)
    } else {
      resolve(value)
    }
  })
};
myPromise.reject = function (reason) {
  return new myPromise((_, reject) => {
    reject(reason);
  })
};
// 并发请求，全成功则resolve，有失败则reject
myPromise.all = function (promises) {
  let resArr = new Array(promises.length);
  let count = 0;
  return new myPromise((resolve, reject) => {
    promises.forEach((promise, index) => {
      // 去除传入的数组中有字面量的影响
      myPromise.resolve(promise).then(value => {
        resArr[index] = value;
        count++;
        if (count === promises.length) {
          resolve(resArr);
        }
      }, reason => {
        reject(reason)
      })
    })
  })
};

// 并发请求，返回所有promises的解决态，外层返回resolve
myPromise.allSettled = function (promises) {
  let resArr = new Array(promises.length);
  let count = 0;
  return new myPromise((resolve, _) => {
    promises.forEach((promise, index) => {
      myPromise.resolve(promise).then(value => {
        resArr[index] = {
          status: 'resolved',
          value
        }
        if (++count === promises.length) {
          resolve(resArr)
        }
      }, reason => {
        resArr[index] = {
          status: 'rejected',
          reason
        }
        if (++count === promises.length) {
          resolve(resArr)
        }
      })
    })
  })
}

// 返回第一个改变了状态的prosmise的状态为它的状态
myPromise.race = function (promises) {
  return new myPromise((resolve, reject) => {
    promises.forEach(promise => {
      myPromise.resolve(promise).then(value => {
        resolve(value)
      }, reason => {
        reject(reason)
      })
    })
  })
};



